//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ArffAttributeSelection.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define MAX_SIZE 500000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ArffAttributeSelection::ArffAttributeSelection () {

  this->toString                    = new String ();
  this->filenameOut                 = new String ();
  this->filenameIn                  = new String ();
  this->patternList                 = new TListE <ArffPatternRecord> ();

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ArffAttributeSelection::ArffAttributeSelection (const ArffAttributeSelection& arffAttributeSelection) {

  this->toString                    = new String (arffAttributeSelection.toString);
  this->filenameOut                 = new String (arffAttributeSelection.filenameOut);
  this->filenameIn                  = new String (arffAttributeSelection.filenameIn);
  this->patternList                 = new TListE <ArffPatternRecord> (arffAttributeSelection.patternList);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ArffAttributeSelection::ArffAttributeSelection (const ArffAttributeSelection* arffAttributeSelection) {

  this->toString                    = new String (arffAttributeSelection->toString);
  this->filenameOut                 = new String (arffAttributeSelection->filenameOut);
  this->filenameIn                  = new String (arffAttributeSelection->filenameIn);
  this->patternList                 = new TListE <ArffPatternRecord> (arffAttributeSelection->patternList);

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ArffAttributeSelection::~ArffAttributeSelection () {

  if (this->toString   ) delete this->toString;
  if (this->filenameOut) delete this->filenameOut;
  if (this->filenameIn ) delete this->filenameIn;
  if (this->patternList) delete this->patternList;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ArffAttributeSelection::FilenameOut (String* filenameOut) {

  if (filenameOut)
    *(this->filenameOut) = *filenameOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ArffAttributeSelection::FilenameIn (String* filenameIn) {

  if (filenameIn)
    *(this->filenameIn) = *filenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ArffAttributeSelection::PatternList (TListE <ArffPatternRecord>* patternList) {

  if (patternList)
    *(this->patternList) = *patternList;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//

String* ArffAttributeSelection::FilenameOut (void) {

  return this->filenameOut;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ArffAttributeSelection::FilenameIn (void) {

  return this->filenameIn;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
TListE <ArffPatternRecord>* ArffAttributeSelection::PatternList (void) {

  return this->patternList;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ArffAttributeSelection::ToString (void) {

  ;
 
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ArffAttributeSelection::LoadSelectionResult (String* type) {

  if (!this->filenameIn || !this->filenameIn->Length() || !this->patternList)
    return false;
  
  ifstream file (this->filenameIn->Out());
  
  if (!file.is_open()) return false;
  
  char  buffer [MAX_SIZE];
  char  patternsPos [MAX_SIZE];
  char* parts = NULL;
  
  bool condLoadPatterns = false;
  
  this->patternList->Clear();
  
  while (!file.eof()) {
    
    file.getline(buffer, MAX_SIZE);
    
    if (condLoadPatterns && this->patternList->SetNext()) {
      this->patternList->GetCurrent()->Pattern()->In(buffer);
      this->patternList->GetCurrent()->Pattern()->RTrim();
    }
    
    if (strstr(buffer, "Selected attributes:") && !condLoadPatterns) {
      
      parts = strtok(buffer, ":");
      if (!parts) return false;
      parts = strtok(NULL, ":");
      if (!parts) return false;
      
      strcpy(patternsPos, parts);
      parts = strtok(patternsPos, ",");
      while (parts) {

        ArffPatternRecord* newArffPatternRecord = new ArffPatternRecord();
        newArffPatternRecord->Position(atoi(parts));
        newArffPatternRecord->Type(type);
        
        this->patternList->Add(newArffPatternRecord);
        parts = strtok(NULL, ",");
        
      }
      
      condLoadPatterns = true;
      
      this->patternList->SetInitial();
      
    }
    
  }
  
  file.close();
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ArffAttributeSelection::LoadDataFromFile (void) {

  if (!this->filenameIn || !this->filenameIn->Length() || !this->patternList)
    return false;
  
  ifstream file (this->filenameIn->Out());
  
  if (!file.is_open()) return false;
  
  char buffer [MAX_SIZE];
  char type [3];
  char pattern [MAX_SIZE];
  int  number = 0;
  int  position;
  
  this->patternList->Clear();
  
  while (!file.eof()) {
    
    file.getline(buffer, MAX_SIZE);
    
    number = sscanf(buffer, "%d %s %s", &position, type, pattern);
    
    if (number == 3) {
      
      ArffPatternRecord* newArffPatternRecord = new ArffPatternRecord();
      
      newArffPatternRecord->Position(position);
      newArffPatternRecord->Pattern()->In(pattern);
      newArffPatternRecord->Type()->In(type);
      
      this->patternList->Add(newArffPatternRecord);
      
    }
    
  }
  
  file.close();
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ArffAttributeSelection::StoreDataInFile (void) {

  if (!this->filenameOut || !this->filenameOut->Length() || !this->patternList)
    return false;
  
  ofstream file (this->filenameOut->Out());
  
  if (!file.is_open())
    return false;
  
  this->patternList->SetInitial();
  while (this->patternList->SetNext()) 
    file << this->patternList->GetCurrent()->ToString()->Out() << endl;  
  
  file.close();
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ArffAttributeSelection::AddDataToFile (void) {

  if (!this->filenameOut || !this->filenameOut->Length() || !this->patternList)
    return false;
  
  fstream file;
  
  file.open(this->filenameOut->Out(), fstream::out | fstream::app);
  if (!file.is_open())
    return false;
  
  file.seekp(0, ofstream::end);
  
  this->patternList->SetInitial();
  while (this->patternList->SetNext()) 
    file << this->patternList->GetCurrent()->ToString()->Out() << endl;  
  
  file.close();
  
  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ArffAttributeSelection::OutPositionPatterns (void) {

  char buffer [MAX_SIZE];
  bool start = false;
  
  memset(buffer, 0x0, MAX_SIZE);
  
  this->patternList->SetInitial();
  while (this->patternList->SetNext()) {
    sprintf(buffer, (start)?"%s,%d\0":"%s%d\0", buffer, this->patternList->GetCurrent()->Position());
    if (!start) start = true;
  }

  this->toString->In(buffer);
  
  return this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ArffAttributeSelection::OutPositionPatterns (int increment) {

  char buffer [MAX_SIZE];
  bool start = false;
  
  memset(buffer, 0x0, MAX_SIZE);
  
  this->patternList->SetInitial();
  while (this->patternList->SetNext()) {
    sprintf(buffer, (start)?"%s,%d\0":"%s%d\0", buffer, this->patternList->GetCurrent()->Position() + increment);
    if (!start) start = true;
  }

  this->toString->In(buffer);
  
  return this->toString;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ArffAttributeSelection ArffAttributeSelection::operator= (const ArffAttributeSelection& arffAttributeSelection) {

  *(this->toString)    = *(arffAttributeSelection.toString);
  *(this->filenameOut) = *(arffAttributeSelection.filenameOut);
  *(this->filenameIn)  = *(arffAttributeSelection.filenameIn);
  *(this->patternList) = *(arffAttributeSelection.patternList);

  return *this;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
